package ferp.core.ai.filter;

import ferp.core.ai.tree2.Evaluator;
import ferp.core.card.Card;
import ferp.core.game.Game;
import ferp.core.game.Trick;
import ferp.core.player.Hand;

/**
 * User: igorgok
 * Date: 1/10/13 5:01 PM
 */
public class FilterHumanPlaysMisere
{
  // we should get here only if human player has declared misere in first two rounds only
  public static int apply(Evaluator.Misere evaluator, int candidates, int player, int trick, int round, int hand, int[] hands)
  {
    switch (hand)
    {
      // todo: makes problem when catching misere - review this case
/*
      case 0:
        {
          int p1 = Game.next(player);
          int p2 = Game.next(p1);
          int filtered1 = candidates;

          // filter out all candidates with suit that declarer does not have
          if (round < 2)
            for (Card.Suit s : Card.Suit.rising)
              if (Hand.only(hands[0], s) == 0)
                filtered1 = Hand.remove(filtered1, s);

          int filtered2 = 0;

          // first hand player shouldn't move from card with suit that is no longer in game
          for (int hash = evaluator.start(filtered1); hash != 0; hash = evaluator.next(filtered1, hash))
          {
            Card c = Card.card(hash);

            if (Hand.only(hands[p1], c.suit) != 0 || Hand.only(hands[p2], c.suit) != 0)
              filtered2 = Hand.add(filtered2, c.hash);
          }

          candidates = filtered2 == 0 ? evaluator.start(candidates) : filtered2;
        }
        break;

*/
      case 1:
        {
          if (round < 2)
          {
            if (Trick.owner(trick, 0) == 0)
            {
              Card c = Trick.card(trick, 0);

              int set1 = Hand.get(hands[player], c.suit);
              Card.Rank lower1 = Card.Set.lower(set1, c.rank);

              if (lower1 == null && set1 != 0)
                return candidates;

              int p2 = Game.next(player);
              int set2 = Hand.get(hands[p2], c.suit);
              Card.Rank lower2 = Card.Set.lower(set2, c.rank);

              if (lower2 == null && set2 != 0)
                return candidates;

              return lower1 == null ? candidates : Hand.add(0, c.suit, lower1);
            }
          }
        }
        break;

      case 2:
        {
          if (round < 2)
          {
            if (Trick.owner(trick, 0) == 0)
            {
              Card c = Trick.card(trick, 0);

              if (c == Trick.highest(trick, Card.Suit.NONE))
              {
                int set = Hand.get(hands[player], c.suit);
                Card.Rank lower = Card.Set.lower(set, c.rank);

                if (lower != null)
                  return Hand.add(0, c.suit, lower);
              }
            }
          }
        }
        break;
    }

    return candidates;
  }
}
